home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 31
/
Aminet 31 (1999)(Schatztruhe)[!][Jun 1999].iso
/
Aminet
/
dev
/
c
/
vbccppcsrc.lha
/
vbcc
/
vlink
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-03-07
|
13KB
|
451 lines
/* $VER: vlink main.c V0.6 (24.10.98)
*
* This file is part of vlink, a portable linker for multiple
* object formats.
* Copyright (c) 1997-99 Frank Wille
*
* vlink is freeware and part of the portable and retargetable ANSI C
* compiler vbcc, copyright (c) 1995-99 by Volker Barthelmann.
* vlink may be freely redistributed as long as no modifications are
* made and nothing is charged for it. Non-commercial usage is allowed
* without any restrictions.
* EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
* SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
*
*
* v0.6 (24.10.98) phx
* -baseoff will modify the base-reg section offset for the
* destination target.
* Deleted obsolete make_baserel_offsets().
* v0.5d (22.08.98) phx
* Faster memory allocation can be activated by #define FASTALLOC.
* v0.5 (27.06.98) phx
* -v shows default target.
* v0.4 (05.06.98) phx
* -sc forces merging of all code sections in an executable.
* -sd forces merging of all data and bss sections in an executable.
* -multibase prevents auto-merging of sections, which are accessed
* base-relative.
* Call linker_relrefs() to find all relative references between
* sections.
* v0.3 (16.04.98) phx
* -R directs vlink to generate short relocs, if the target format
* allows this. It is for example supported by ELF and AmigaDos.
* New option -F for reading a list of input files.
* v0.2 (07.03.98) phx
* -v shows standard library path.
* v0.1 (27.02.98) phx
* First version that seems to link AmigaOS ADOS and EHF
* objects and libraries. Many common features, like linking
* sections together which have relative references, are
* still missing. Also, PowerPC-ELF32 support is about to come.
* v0.0 (04.08.97) phx
* File created. Project started on a beautiful summer-day
* at the North Sea beach of Cuxhaven. :)
*/
#define MAIN_C
#include "vlink.h"
struct GlobalVars gvars;
void cleanup(struct GlobalVars *);
static char *get_option_arg(int,char *[],int *);
static void ReadListFile(struct GlobalVars *,char *);
main(int argc,char *argv[])
{
struct GlobalVars *gv = &gvars;
int i,j;
char *buf;
struct LibPath *libp;
struct InputFile *ifn;
bool stdlib;
bool dynamic = TRUE; /* link with dynamic libraries first */
int so_version = 0; /* minum version for shared objects */
#ifdef FASTALLOC
init_mem();
#endif
/* initialize and set default values */
memset(gv,0,sizeof(struct GlobalVars));
initlist(&gv->libpaths);
#ifdef LIBPATH
libp = alloc(sizeof(struct LibPath));
libp->path = LIBPATH; /* default search path */
addtail(&gv->libpaths,&libp->n);
stdlib = TRUE;
#else
stdlib = FALSE;
#endif
#ifdef DEFTARGET
for (j=0; fff[j]; j++) {
if (!strcmp(fff[j]->tname,DEFTARGET)) {
gv->dest_format = (uint8)j;
break;
}
}
if (fff[j] == NULL) {
fprintf(stderr,"Configuration warning: Selected default target "
"\"%s\" is not included.\nThe current default target "
"is \"%s\".\n",DEFTARGET,fff[gv->dest_format]->tname);
printf("\n");
}
#endif
initlist(&gv->inputlist);
initlist(&gv->lnksec);
gv->dest_name = "a.out";
gv->maxerrors = DEF_MAXERRORS;
if (argc<2 || (argc==2 && *argv[1]=='?')) {
show_usage();
exit(EXIT_SUCCESS);
}
for (i=1; i<argc; i++) {
if (*argv[i] == '-') { /* option detected */
switch (argv[i][1]) {
case 'b':
if (!strcmp(&argv[i][2],"aseoff")) { /* set base-relative offset */
++i;
if (i<argc && *argv[i]!='-') {
long bo;
sscanf(argv[i],"%li",&bo);
fff[gv->dest_format]->baseoff = bo;
}
else
error(34,argv[--i]); /* option requires argument */
}
else { /* select target format */
if (buf = get_option_arg(argc,argv,&i)) {
for (j=0; fff[j]; j++)
if (!strcmp(fff[j]->tname,buf))
break;
if (fff[j])
gv->dest_format = (uint8)j;
else
error(9,buf); /* invalid target format */
}
else
error(5,'b'); /* option requires argument */
}
break;
case 'd':
if (buf = get_option_arg(argc,argv,&i)) {
switch (*buf) {
case 'n': /* static */
dynamic = FALSE;
break;
case 'y': /* dynamic */
dynamic = TRUE;
break;
case 'c':
gv->alloc_common = TRUE; /* force alloc. of common syms. */
break;
case 'p':
/* @@@ something with procedures... don't know */
break;
default:
error(4,*buf); /* unknown argument for option -d */
break;
}
}
else
error(5,'d'); /* option requires argument */
break;
case 'h': /* help text */
show_usage();
exit(EXIT_SUCCESS);
case 'l': /* library specifier */
if (buf = get_option_arg(argc,argv,&i)) {
ifn = alloc(sizeof(struct InputFile));
ifn->name = buf;
ifn->lib = TRUE;
ifn->dynamic = dynamic;
ifn->so_ver = so_version;
so_version = 0;
addtail(&gv->inputlist,&ifn->n);
}
else
error(5,'l'); /* option requires argument */
break;
case 'm':
if (!strcmp(&argv[i][2],"ultibase"))
gv->multibase = TRUE;
else
error(2,argv[i]); /* unrecognized option */
break;
case 'n':
if (!strcmp(&argv[i][2],"ostdlib")) {
if (stdlib) {
remhead(&gv->libpaths);
stdlib = FALSE;
}
}
else
error(2,argv[i]); /* unrecognized option */
break;
case 'o': /* set output file name */
if (!(gv->dest_name = get_option_arg(argc,argv,&i)))
error(5,'o'); /* option requires argument */
break;
case 'r': /* output is an relocatable object again */
gv->dest_object = TRUE;
break;
case 's':
switch (argv[i][2]) {
case '\0': /* strip all symbols */
gv->strip_symbols = STRIP_ALL;
break;
case 'c': /* -sc force small code */
gv->small_code = TRUE;
break;
case 'd': /* -d force small data */
gv->small_code = TRUE;
break;
case 't': /* -static */
dynamic = FALSE;
break;
default:
error(2,argv[i]); /* unrecognized option */
break;
}
break;
case 't': /* trace file accesses */
gv->trace_file = stderr;
break;
case 'u': /* mark symbol as undefined */
/* @@@ ... */
break;
case 'v': /* show version and target info */
show_version();
printf("Standard library path: %s\nDefault target: %s\n"
"Supported targets:", stdlib ?
((struct LibPath *)(gv->libpaths.first))->path : "none",
fff[gv->dest_format]->tname);
for (j=0; fff[j]; j++)
printf(" %s",fff[j]->tname);
printf("\n");
exit(EXIT_SUCCESS);
case 'w': /* suppress warnings */
gv->dontwarn = TRUE;
break;
case 'x': /* discard all local symbols */
gv->discard_local = DISLOC_ALL;
break;
case 'y': /* trace all accesses on a specific symbol */
if (gv->trace_syms == NULL)
gv->trace_syms = alloc_hashtable(TRSYMHTABSIZE);
if (buf = get_option_arg(argc,argv,&i)) {
struct SymNames **chain =
&gv